/*
 * Copyright (c) 2017 Baidu, Inc. All Rights Reserve.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package start.spring.basic.service;

import java.text.ParseException;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.baidu.fsg.uid.utils.DockerUtils;
import com.baidu.fsg.uid.utils.NetUtils;
import com.baidu.fsg.uid.worker.WorkerIdAssigner;
import com.baidu.fsg.uid.worker.WorkerNodeType;
import com.baomidou.dynamic.datasource.annotation.DS;

import start.spring.basic.constant.CommonConstant;
import start.spring.basic.dao.WorkerNodeMapper;
import start.spring.basic.dynamic.DsConstant;
import start.spring.basic.dynamic.SpringJdbc;
import start.spring.basic.entity.WorkerNode;
import start.spring.basic.util.common.DateUtil;
import start.spring.basic.util.common.LoggerFilePort;

/**
 * Represents an implementation of {@link WorkerIdAssigner}, 
 * the worker id will be discarded after assigned to the UidGenerator
 * 
 * @author yutianbao
 */
@Service("disposableWorkerIdAssigner")
public class DisposableWorkerIdAssigner implements WorkerIdAssigner {
	
	@Autowired
	protected SpringJdbc dao;
	
    @Resource
    private WorkerNodeMapper workerNodeMapper;
    
    @Value("${spring.datasource.dynamic.datasource.sysconfig.url}")
    private String dbUrl;
    

    /**
     * Assign worker id base on database.<p>
     * If there is host name & port in the environment, we considered that the node runs in Docker container<br>
     * Otherwise, the node runs on an actual machine.
     * 
     * @return assigned worker id
     */
    @DS(DsConstant.SYSCONFIG)
    @Override
	public long assignWorkerId() {
    	
        WorkerNode workerNodeEntity = buildWorkerNode();
        
        //oracle数据库，id无法自增采用序列的方式，其它数据库默认采用类似mysql的id自增的方式
        if(dbUrl.indexOf("jdbc:oracle")==0) {
        	Map<String,Object> idNode = dao.getOne("select SEQ_WORK_NODE.NEXTVAL from dual", null);
            workerNodeEntity.setId(Long.parseLong(idNode.get("NEXTVAL").toString()));
        }
        
        try {
			workerNodeEntity.setLaunchDate(DateUtil.parse(CommonConstant.EPOCH_STR, DateUtil.FORMAT_YMD_L));
		} catch (ParseException e) {
			e.printStackTrace();
		}
        workerNodeMapper.addWorkerNode(workerNodeEntity);
        return workerNodeEntity.getId();
    }

    /**
     * Build worker node entity by IP and PORT
     */
    private WorkerNode buildWorkerNode() {
    	WorkerNode workerNodeEntity = new WorkerNode();
    	String port = new LoggerFilePort().getPropertyValue();
        if (DockerUtils.isDocker()) {
        	//docker环境下记录启动容器的内部ip
            workerNodeEntity.setType(WorkerNodeType.CONTAINER.value());
            workerNodeEntity.setHostName(NetUtils.getLocalAddress());
            workerNodeEntity.setPort(port);
        } else {
            workerNodeEntity.setType(WorkerNodeType.ACTUAL.value());
            workerNodeEntity.setHostName(NetUtils.getLocalAddress());
            workerNodeEntity.setPort(port);
        }
        return workerNodeEntity;
    }

}
